using System;
using System.IO;

public class NetworkStream : Stream
{
    private byte[] _buffer = null;
    private int _offset = 0;

    public NetworkStream(byte[] buffer)
        : this(buffer,0,buffer.Length)
    {

    }

    public NetworkStream(byte[] buffer, int size)
        : this(buffer, 0, size)
    {

    }

    public NetworkStream(byte[] buffer,int offset,int size)
    {
        checkBufferArg(buffer, offset, size);

        _buffer = buffer;
        _length = size;
        _offset = offset;
    }

    private long _position = 0;
    public override long Position
    {
        get
        {
            return _position;
        }
        set
        {
            if (value < 0 || value > _length)
                throw new ArgumentOutOfRangeException();
            _position = value;
        }
    }

    private long _length = 0;
    public override long Length
    {
        get { return _length; }
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }
    public override bool CanWrite
    {
        get { return true; }
    }
    
    public override void Flush()
    {

    }

    private static void checkBufferArg(byte[] buffer, int offset, int count)
    {
        if (null == buffer)
            throw new ArgumentNullException();

        if (offset < 0 || count < 0)
            throw new ArgumentOutOfRangeException();

        if (buffer.Length < offset + count)
            throw new ArgumentException();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        checkBufferArg(buffer, offset, count);

        int retCount = Math.Min((int)(_length - _position), count);
        if (retCount > 0)
        {
            Array.Copy(_buffer, _offset + _position, buffer, offset, retCount);
        }
        _position += retCount;

        return retCount;
    }

    public override void Write(byte[] buffer, int offset,int count)
    {
        checkBufferArg(buffer, offset, count);

        if (_length - _position < count)
            throw new IOException();

        Array.Copy(buffer, offset, _buffer, _offset + _position, count);

        _position += count;
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }

    public override long Seek(long offset,SeekOrigin origin)
    {
        throw new NotSupportedException();
    }
}

public class NetworkInputStream : Stream
{
    private NetworkStream _stream = null;

    public NetworkInputStream(NetworkStream stream)
    {
        if (null == stream)
            throw new ArgumentNullException();

        _stream = stream;
    }

    public override long Position
    {
        get
        {
            return _stream.Position;
        }
        set
        {
            _stream.Position = value;
        }
    }

    public override long Length
    {
        get { return _stream.Position; }
    }

    public override bool CanRead
    {
        get { return false; }
    }
    public override bool CanSeek
    {
        get { return false; }
    }
    public override bool CanWrite
    {
        get { return true; }
    }

    public override void Flush()
    {

    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        _stream.Write(buffer, offset, count);
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException();
    }
}